#include "user.h"
/*
 * Only use LoRa mode!!!!!!
 */

#define RSSI_OFFSET_LF                              -164
#define RSSI_OFFSET_HF                              -157



#define RSSI_OFFSET                                 -139

#define SX_API_DBG	DBG_INFO
//#define SX_API_DBG(X,Y...)
typedef struct
{
    uint8_t       Addr;
    uint8_t       Value;
}RadioRegisters_t;

const RadioRegisters_t SX127X_FskRegsInit[] =
{
		{ REG_OCP                , 0x3B },
	    //{ REG_LNA                , 0x20 },
	    { REG_RXCONFIG           , 0x1E },
	    { REG_RSSICONFIG         , 0xD2 },
	    { REG_AFCFEI             , 0x01 },
	    { REG_PREAMBLEDETECT     , 0xAA },
	    { REG_OSC                , 0x07 },
	    { REG_SYNCCONFIG         , 0x12 },
	    { REG_SYNCVALUE1         , 0xC1 },
	    { REG_SYNCVALUE2         , 0x94 },
	    { REG_SYNCVALUE3         , 0xC1 },
	    { REG_PACKETCONFIG1      , 0xD8 },
	    { REG_FIFOTHRESH         , 0x8F },
	    { REG_IMAGECAL           , 0x82 },
};

const RadioRegisters_t SX127X_LoRaRegsInit[] =
{

		{ REG_LR_FIFOTXBASEADDR     , 0x00 },
		{ REG_LR_FIFORXBASEADDR     , 0x00 },
		{ REG_LR_DIOMAPPING1        , 0x02 },
	    { REG_LR_DIOMAPPING2        , 0x00 },
		{ REG_LR_IRQFLAGSMASK		, 0xff },
};

void SX127X_PrintReg(uint8_t SpiID, uint8_t Reg)
{
	int32_t Error;
	uint8_t Buf[2];
	Buf[0] = Reg;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	SX_API_DBG("%02x %02x %d", Reg, Buf[1], Error);
}

uint32_t SX127X_ChannelToFreq(uint32_t channel)
{
	uint32_t initialChanInt, initialChanFrac;

	initialChanInt = channel  >> 8;
	initialChanFrac = channel - ( initialChanInt << 8 );
	return initialChanInt * FREQ_STEP_8 + ( ( initialChanFrac * FREQ_STEP_8 +  128  ) >> 8 );
}

uint32_t SX127X_FreqToChannel(uint32_t freq)
{
	uint32_t initialFreqInt, initialFreqFrac;
	initialFreqInt = freq / FREQ_STEP_8;
	initialFreqFrac = freq - ( initialFreqInt * FREQ_STEP_8 );
	return ( initialFreqInt << 8 ) + ( ( ( initialFreqFrac << 8 ) + ( FREQ_STEP_8 / 2 ) ) / FREQ_STEP_8 );
}


int32_t SX127X_SPISync(uint8_t SpiID, uint8_t *Byte, uint8_t Len)
{
	return SPI_Xfer(SpiID, Byte, Byte, Len, 0, 1);
}

uint8_t SX127X_ReadReg(uint8_t SpiID, uint8_t Reg, int32_t *Error)
{
	uint8_t Buf[2];
	Buf[0] = Reg;
	*Error = SX127X_SPISync(SpiID, Buf, 2);
	return Buf[1];
}

int32_t SX127X_WriteReg(uint8_t SpiID, uint8_t Reg, uint8_t Value)
{

	uint8_t Buf[2];
	Buf[0] = Reg|0x80;
	Buf[1] = Value;
	return SX127X_SPISync(SpiID, Buf, 2);
}

int32_t SX127X_WriteAndVerifyReg(uint8_t SpiID, uint8_t Reg, uint8_t Value)
{
	int32_t Error;
	uint8_t Buf[2];
	Buf[0] = Reg|0x80;
	Buf[1] = Value;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	Buf[0] = Reg;
	Buf[1] = Value + 1;
	Error = SX127X_SPISync(SpiID, Buf, 2);

	if (Error)
	{
		SX_API_DBG("%02x %02x %02x", Reg, Buf[1], Value);
		return Error;
	}

	if (Buf[1] != Value)
	{
		SX_API_DBG("%02x %02x %02x", Reg, Buf[1], Value);
    	return -ERROR_DEV_OP_FAIL;
	}
	else
	{

		return ERROR_NONE;
	}
}

int32_t SX127X_ModifyReg(uint8_t SpiID, uint8_t Reg, uint8_t Mask, uint8_t Value)
{
	int32_t Error;
	uint8_t Buf[2];
	Buf[0] = Reg;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	if (Error)
		return Error;
	Buf[1] = (Buf[1] & Mask) | Value;
	Buf[0] = Reg|0x80;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	if (Error)
		return Error;
	return ERROR_NONE;
}

int32_t SX127X_ModifyAndVerifyReg(uint8_t SpiID, uint8_t Reg, uint8_t Mask, uint8_t Value)
{
	int32_t Error;
	uint8_t Buf[2];
	Buf[0] = Reg;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	if (Error)
		return Error;
	Buf[1] = (Buf[1] & Mask) | Value;
	Buf[0] = Reg|0x80;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	if (Error)
		return Error;
	Buf[0] = Reg;
	Error = SX127X_SPISync(SpiID, Buf, 2);
	if (Error)
		return Error;
	if ( (Value & (~Mask)) != (Buf[1] & (~Mask)) )
	{
		SX_API_DBG("%02x %02x %02x", Reg, (Value & (~Mask)), (Buf[1] & (~Mask)));
		return -ERROR_DEV_OP_FAIL;
	}
	return ERROR_NONE;
}

int32_t SX127X_ReadfifoSync(uint8_t SpiID, uint8_t *Buf, uint8_t DataLen)
{
	Buf[0] = 0;
	return SX127X_SPISync(SpiID, Buf, DataLen + 1);
}

int32_t SX127X_WritefifoSync(uint8_t SpiID, uint8_t *Buf, uint8_t DataLen)
{
	Buf[0] = 0x80;
	return SX127X_SPISync(SpiID, Buf, DataLen + 1);
}

int32_t SX127X_ReadfifoASync(uint8_t SpiID, uint8_t *Buf, uint8_t DataLen)
{
	Buf[0] = 0;
	return SPI_Xfer(SpiID, Buf, Buf, DataLen + 1, 1, 1);
}

int32_t SX127X_WritefifoASync(uint8_t SpiID, uint8_t *Buf, uint8_t DataLen)
{
	Buf[0] = 0x80;
	return SPI_Xfer(SpiID, Buf, Buf, DataLen + 1, 1, 1);
}

int32_t SX127X_SetOpMode( uint8_t SpiID, uint8_t opMode )
{
	uint8_t NewValue;
	int32_t Error;
	Error = SX127X_ModifyReg( SpiID, REG_OPMODE, RF_OPMODE_MASK, opMode);
    NewValue = SX127X_ReadReg( SpiID, REG_OPMODE, &Error);
    if ( (NewValue & (~RF_OPMODE_MASK)) == opMode )
    {
    	return ERROR_NONE;
    }
    else
    {
    	SX_API_DBG("%02x %02x %d", NewValue, opMode, Error);
    	if (Error)
    		return Error;
    	return -ERROR_DEV_OP_FAIL;
    }
}

int32_t SX127X_SetOpModeWithoutCheck( uint8_t SpiID, uint8_t opMode )
{
	return SX127X_ModifyReg( SpiID, REG_OPMODE, RF_OPMODE_MASK, opMode);
}

int32_t SX127X_GetOpMode(uint8_t SpiID, uint8_t *opMode)
{
	int32_t Error;
	*opMode = (SX127X_ReadReg( SpiID, REG_OPMODE, &Error)  & (~RF_OPMODE_MASK));
	return Error;
}

int32_t SX127X_SetModem(uint8_t SpiID, uint8_t IsLoRa)
{
	uint8_t CurMode;
	uint8_t NewValue;
	int32_t Error;
	CurMode = SX127X_ReadReg( SpiID, REG_OPMODE, &Error) & (~RF_OPMODE_MASK);
	SX127X_SetOpMode(SpiID, RF_OPMODE_SLEEP);
	SX127X_ModifyReg(SpiID, REG_OPMODE, RF_OPMODE_LONGRANGEMODE_MASK, (IsLoRa)?RF_OPMODE_LONGRANGEMODE_ON:RF_OPMODE_LONGRANGEMODE_OFF );
	NewValue = SX127X_ReadReg( SpiID, REG_OPMODE, &Error);
    if ( (NewValue & (~RF_OPMODE_LONGRANGEMODE_MASK)) == ((IsLoRa)?RF_OPMODE_LONGRANGEMODE_ON:RF_OPMODE_LONGRANGEMODE_OFF) )
    {

    }
    else
    {
    	SX_API_DBG("%02x %d", NewValue, Error);
    	if (Error)
    		return Error;
    	return -ERROR_DEV_OP_FAIL;
    }
	return SX127X_SetOpMode(SpiID, CurMode);
}

int32_t SX127X_ReadRssi( uint8_t SpiID, RadioLoRaSettings_t *Setting, int16_t *Rssi)
{
    int32_t Error;
    switch (Setting->ChipVersion)
    {
    case __SX1272_CHIP_VERSION__:
    	*Rssi = RSSI_OFFSET + SX127X_ReadReg( SpiID, REG_LR_RSSIVALUE, &Error );
    	break;
    case __SX1276_CHIP_VERSION__:
    	if (Setting->CurFreq > RF_MID_BAND_THRESH)
    	{
    		*Rssi = RSSI_OFFSET_HF + SX127X_ReadReg( SpiID, REG_LR_RSSIVALUE, &Error );
    	}
    	else
    	{
    		*Rssi = RSSI_OFFSET_LF + SX127X_ReadReg( SpiID, REG_LR_RSSIVALUE, &Error );
    	}
    }
    return Error;
}

int32_t SX127X_SetChannel( uint8_t SpiID, uint32_t Freq )
{
    uint32_t channel = SX127X_FreqToChannel( Freq );
    uint8_t Buf[4];
    uint8_t Byte[3];
    int32_t Error;
    Buf[0] = REG_FRFMSB|0x80;
    Byte[0] = ( channel >> 16 ) & 0xFF;
    Byte[1] = ( channel >> 8 ) & 0xFF;
    Byte[2] = channel & 0xFF;
    SX_API_DBG("%02x %02x %02x", Byte[0], Byte[1], Byte[2]);
    memcpy(Buf + 1, Byte, 3);
    Error = SX127X_SPISync(SpiID, Buf, 4);

    memset(Buf, 0, 4);
    Buf[0] = REG_FRFMSB;
    Error = SX127X_SPISync(SpiID, Buf, 4);

    if (memcmp(Buf + 1, Byte, 3))
    {
    	SX_API_DBG("%02x %02x %02x %02x %02x %02x", Byte[0], Byte[1], Byte[2], Buf[1], Buf[2], Buf[3]);
    	return -ERROR_DEV_OP_FAIL;
    }
    return Error;
}

int32_t SX127X_ClearIrq(uint8_t SpiID, uint8_t IrqFlag)
{
	return SX127X_WriteReg(SpiID, REG_LR_IRQFLAGS, IrqFlag);
}

int32_t SX127X_ReadAndClearIrq(uint8_t SpiID, uint8_t *IrqFlag)
{
	int32_t Error;
	*IrqFlag = SX127X_ReadReg(SpiID, REG_LR_IRQFLAGS, &Error);
	if (Error)
		return Error;
	return SX127X_WriteReg(SpiID, REG_LR_IRQFLAGS, *IrqFlag);
}

int32_t SX127X_EnableIrq(uint8_t SpiID, uint8_t IrqFlag)
{
	return SX127X_ModifyAndVerifyReg(SpiID, REG_LR_IRQFLAGSMASK, ~IrqFlag, ~IrqFlag);
}

int32_t SX127X_DisableIrq(uint8_t SpiID, uint8_t IrqFlag)
{
	return SX127X_ModifyAndVerifyReg(SpiID, REG_LR_IRQFLAGSMASK, ~IrqFlag, IrqFlag);
}

int32_t SX127X_ChipInit(uint8_t SpiID)
{
	int32_t i;
	int32_t Error = SX127X_SetModem(SpiID, 0);
	if (Error)
		return Error;

	for(i = 0; i < sizeof(SX127X_FskRegsInit)/sizeof(RadioRegisters_t); i++)
	{
		if (SX127X_WriteAndVerifyReg(SpiID, SX127X_FskRegsInit[i].Addr, SX127X_FskRegsInit[i].Value))
		{
			return -ERROR_DEV_OP_FAIL;
		}
	}
	SX127X_SetModem(SpiID, 1);
	SX127X_ClearIrq(SpiID, 0xff);
	for(i = 0; i < sizeof(SX127X_LoRaRegsInit)/sizeof(RadioRegisters_t); i++)
	{
		if (SX127X_WriteAndVerifyReg(SpiID, SX127X_LoRaRegsInit[i].Addr, SX127X_LoRaRegsInit[i].Value))
		{
			return -ERROR_DEV_OP_FAIL;
		}
	}
	Error = SX127X_ModifyAndVerifyReg(SpiID, REG_LNA, RF_LNA_BOOST_MASK, RF_LNA_BOOST_ON);
	if (Error)
		return Error;
	return SX127X_SetModem(SpiID, RFLR_OPMODE_STANDBY);
}

int32_t SX127X_StartCal(uint8_t SpiID)
{
	int32_t Error;
	Error = SX127X_SetModem(SpiID, 0);
	if (Error)
		return Error;
	Error = SX127X_WriteAndVerifyReg(SpiID, REG_PACONFIG, 0);
	if (Error)
		return Error;
	return SX127X_ModifyReg(SpiID, REG_IMAGECAL, RF_IMAGECAL_IMAGECAL_MASK, RF_IMAGECAL_IMAGECAL_START);
}

int32_t SX127X_CheckCalDone(uint8_t SpiID)
{
	int32_t Error;
	uint8_t Value;
	Value = SX127X_ReadReg(SpiID, REG_IMAGECAL, &Error);
	if (Error)
		return Error;
	if (Value & RF_IMAGECAL_IMAGECAL_RUNNING)
	{
		return -ERROR_DEV_OP_PROCESS;
	}
	else
	{
		Error = SX127X_SetModem(SpiID, 1);
		if (Error)
			return Error;
		return -ERROR_NONE;
	}
}

int32_t SX127X_SetTxPower(uint8_t SpiID, uint8_t ChipID, uint8_t Power, uint8_t PaSelect)
{
    uint8_t paConfig = 0;
    uint8_t paDac = 0;
    int32_t Error;

    SX_API_DBG("%d %02x", Power, PaSelect);

    switch (ChipID)
    {
    case __SX1272_CHIP_VERSION__:
    	paDac = SX127X_ReadReg( SpiID, REG_SX1272_PADAC, &Error );
    	break;
    case __SX1276_CHIP_VERSION__:
    	paDac = SX127X_ReadReg( SpiID, REG_SX1276_PADAC, &Error );
    	break;
    }

    if (Error)
    	return Error;

    switch (ChipID)
    {
    case __SX1272_CHIP_VERSION__:
    	paDac = SX127X_ReadReg( SpiID, REG_SX1272_PADAC, &Error );

        if( PaSelect)
        {
            if( Power > 17 )
            {
                paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
            }
            else
            {
                paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
            }
            if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
            {
                if( Power < 5 )
                {
                	Power = 5;
                }
                if( Power > 20 )
                {
                	Power = 20;
                }
                paConfig = PaSelect | ( ( Power - 5 ) & 0x0F );
            }
            else
            {
                if( Power < 2 )
                {
                	Power = 2;
                }
                if( Power > 17 )
                {
                	Power = 17;
                }
                paConfig = PaSelect | ( ( Power - 2 ) & 0x0F );
            }
        }
        else
        {
            if( Power > 13 )
            {
            	Power = 13;
            }
            paConfig = ( Power + 1 ) & 0x0F ;
        }
        SX_API_DBG("%02x %02x", paConfig, paDac);
        Error = SX127X_WriteAndVerifyReg( SpiID, REG_PACONFIG, paConfig );
        if (Error)
        	return Error;
        Error = SX127X_WriteAndVerifyReg( SpiID, REG_SX1272_PADAC, paDac );
        if (Error)
        	return Error;
    	break;
    case __SX1276_CHIP_VERSION__:
    	paDac = SX127X_ReadReg( SpiID, REG_SX1276_PADAC, &Error );
        if( PaSelect)
        {
            if( Power > 17 )
            {
                paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
            }
            else
            {
                paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
            }
            if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
            {
                if( Power < 5 )
                {
                	Power = 5;
                }
                if( Power > 20 )
                {
                	Power = 20;
                }
                paConfig = PaSelect | 0x70 | ( ( Power - 5 ) & 0x0F );
            }
            else
            {
                if( Power < 2 )
                {
                	Power = 2;
                }
                if( Power > 17 )
                {
                	Power = 17;
                }
                paConfig = PaSelect | 0x70| ( ( Power - 2 ) & 0x0F );
            }
        }
        else
        {
            if( Power > 14 )
            {
            	Power = 14;
            }
            paConfig = Power|0x70;
        }
        SX_API_DBG("%02x %02x", paConfig, paDac);
        Error = SX127X_WriteAndVerifyReg( SpiID, REG_PACONFIG, paConfig );
        if (Error)
        	return Error;
        Error = SX127X_WriteAndVerifyReg( SpiID, REG_SX1276_PADAC, paDac );
        if (Error)
        	return Error;
    	break;
    }
		return ERROR_NONE;
}

int32_t SX127X_SetConfig(uint8_t SpiID, RadioLoRaSettings_t *Setting)
{
	int32_t Error;
	uint8_t Power;
	uint8_t Temp;
	uint8_t PaSelect = RF_PACONFIG_PASELECT_RFO;
	uint8_t Buf[9];
	uint8_t Reg[8];
	uint8_t LowData = 0;
	uint8_t ImplicitHeader = 0;
	uint8_t Coderate, Bandwidth;

	if (Setting->CurFreq == Setting->RFHFreq)
	{
		if (Setting->PABoostSW & SX127X_BOOST_RFH)
		{
			PaSelect = RF_PACONFIG_PASELECT_PABOOST;
		}
		Power = Setting->RFHPower;
	}
	else if (Setting->CurFreq == Setting->RFLFreq)
	{
		if (Setting->PABoostSW & SX127X_BOOST_RFL)
		{
			PaSelect = RF_PACONFIG_PASELECT_PABOOST;
		}
		Power = Setting->RFLPower;
	}
	else
	{
		return -ERROR_PARAM_ILLEGAL;
	}
	Error = SX127X_SetChannel(SpiID, Setting->CurFreq);
	if (Error)
		return Error;
	Error = SX127X_SetTxPower(SpiID, Setting->ChipVersion, Power, PaSelect);
	if (Error)
		return Error;

    if( ( ( Setting->Bandwidth == SX127X_LORA_BW_125K ) && ( ( Setting->Datarate == RFLR_MODEMCONFIG2_SF_11 ) || ( Setting->Datarate == RFLR_MODEMCONFIG2_SF_12 ) ) ) ||
        ( ( Setting->Bandwidth == SX127X_LORA_BW_250K ) && ( Setting->Datarate == RFLR_MODEMCONFIG2_SF_12 ) ) )
    {
    	LowData = 1;
    }

    if (Setting->ImplicitHeader || Setting->Datarate == RFLR_MODEMCONFIG2_SF_6)
    {
    	ImplicitHeader = 1;
    	Error = SX127X_ModifyAndVerifyReg(SpiID, REG_LR_DETECTOPTIMIZE, RFLR_DETECTIONOPTIMIZE_MASK, RFLR_DETECTIONOPTIMIZE_SF6);
		if (Error)
			return Error;

		Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF6);
		if (Error)
			return Error;

    }
    else
    {
    	Error = SX127X_ModifyAndVerifyReg(SpiID, REG_LR_DETECTOPTIMIZE, RFLR_DETECTIONOPTIMIZE_MASK, RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12);
    	if (Error)
			return Error;

		Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12);
		if (Error)
			return Error;

    }

    memset(Reg, 0, sizeof(Reg));
	if (Setting->ImplicitPayloadLen)
	{
		Reg[REG_LR_PAYLOADLENGTH - REG_LR_MODEMCONFIG1] = Setting->ImplicitPayloadLen;
	}
	else
	{
		Reg[REG_LR_PAYLOADLENGTH - REG_LR_MODEMCONFIG1] = 0xff;
	}
	if (Setting->PayloadMaxLen)
	{
		Reg[REG_LR_PAYLOADMAXLENGTH - REG_LR_MODEMCONFIG1] = Setting->PayloadMaxLen;
	}
	else
	{
		Reg[REG_LR_PAYLOADMAXLENGTH - REG_LR_MODEMCONFIG1] = 0xff;
	}
	Reg[REG_LR_SYMBTIMEOUTLSB - REG_LR_MODEMCONFIG1] = Setting->RxTimeout & 0x00ff;
	Reg[REG_LR_PREAMBLEMSB - REG_LR_MODEMCONFIG1] = (Setting->PreambleLen >> 8) & 0x00ff;
	Reg[REG_LR_PREAMBLELSB - REG_LR_MODEMCONFIG1] = Setting->PreambleLen & 0x00ff;
	Reg[REG_LR_HOPPERIOD - REG_LR_MODEMCONFIG1] = Setting->HopPeriod;

    switch (Setting->ChipVersion)
    {
    case __SX1272_CHIP_VERSION__:
    	switch (Setting->Bandwidth)
    	{
    	case SX127X_LORA_BW_125K:
    		Bandwidth = RFLR_SX1272_MODEMCONFIG1_BW_125_KHZ;
    		break;
    	case SX127X_LORA_BW_250K:
    		Bandwidth = RFLR_SX1272_MODEMCONFIG1_BW_250_KHZ;
    		break;
    	case SX127X_LORA_BW_500K:
    		Bandwidth = RFLR_SX1272_MODEMCONFIG1_BW_500_KHZ;
    		break;
    	default:
    		return -ERROR_PARAM_ILLEGAL;
    	}

    	switch (Setting->Coderate)
    	{
    	case SX127X_LORA_CODERATE_5:
    		Coderate = RFLR_SX1272_MODEMCONFIG1_CODINGRATE_4_5;
    		break;
    	case SX127X_LORA_CODERATE_6:
    		Coderate = RFLR_SX1272_MODEMCONFIG1_CODINGRATE_4_6;
    		break;
    	case SX127X_LORA_CODERATE_7:
    		Coderate = RFLR_SX1272_MODEMCONFIG1_CODINGRATE_4_7;
    		break;
    	case SX127X_LORA_CODERATE_8:
    		Coderate = RFLR_SX1272_MODEMCONFIG1_CODINGRATE_4_8;
    		break;
    	default:
    		return -ERROR_PARAM_ILLEGAL;
    	}
    	Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] = Bandwidth|Coderate;
    	if (ImplicitHeader)
    	{

    		Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] |= RFLR_SX1272_MODEMCONFIG1_IMPLICITHEADER_ON;
    	}

		if (Setting->CrcOn)
		{
			Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] |= RFLR_SX1272_MODEMCONFIG1_RXPAYLOADCRC_ON;
		}
		if (LowData)
		{
			Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] |= RFLR_SX1272_MODEMCONFIG1_LOWDATARATEOPTIMIZE_ON;
		}

		Reg[REG_LR_MODEMCONFIG2 - REG_LR_MODEMCONFIG1] = Setting->Datarate|Setting->TxContinuous|(Setting->RxTimeout >> 8);
    	if (Setting->AGCAuto)
    	{
    		Reg[REG_LR_MODEMCONFIG2 - REG_LR_MODEMCONFIG1] |= RFLR_SX1272_MODEMCONFIG2_AGCAUTO_ON;
    	}

    	if (Setting->HopPeriod)
    	{
    		Error = SX127X_ModifyAndVerifyReg(SpiID, REG_LR_SX1272_PLLHOP, RFLR_PLLHOP_FASTHOP_MASK, RFLR_PLLHOP_FASTHOP_ON);
    		if (Error)
    			return Error;
    	}
    	break;

    case __SX1276_CHIP_VERSION__:
    	switch (Setting->Bandwidth)
    	{
    	case SX127X_LORA_BW_125K:
    		Bandwidth = RFLR_SX1276_MODEMCONFIG1_BW_125_KHZ;
    		break;
    	case SX127X_LORA_BW_250K:
    		Bandwidth = RFLR_SX1276_MODEMCONFIG1_BW_250_KHZ;
    		break;
    	case SX127X_LORA_BW_500K:
    		Bandwidth = RFLR_SX1276_MODEMCONFIG1_BW_500_KHZ;
    		break;
    	default:
    		return -ERROR_PARAM_ILLEGAL;
    	}

    	switch (Setting->Coderate)
    	{
    	case SX127X_LORA_CODERATE_5:
    		Coderate = RFLR_SX1276_MODEMCONFIG1_CODINGRATE_4_5;
    		break;
    	case SX127X_LORA_CODERATE_6:
    		Coderate = RFLR_SX1276_MODEMCONFIG1_CODINGRATE_4_6;
    		break;
    	case SX127X_LORA_CODERATE_7:
    		Coderate = RFLR_SX1276_MODEMCONFIG1_CODINGRATE_4_7;
    		break;
    	case SX127X_LORA_CODERATE_8:
    		Coderate = RFLR_SX1276_MODEMCONFIG1_CODINGRATE_4_8;
    		break;
    	default:
    		return -ERROR_PARAM_ILLEGAL;
    	}
    	Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] = Bandwidth|Coderate;
    	if (ImplicitHeader)
    	{

    		Reg[REG_LR_MODEMCONFIG1 - REG_LR_MODEMCONFIG1] |= RFLR_SX1276_MODEMCONFIG1_IMPLICITHEADER_ON;
    	}
    	Reg[REG_LR_MODEMCONFIG2 - REG_LR_MODEMCONFIG1] = Setting->Datarate|Setting->TxContinuous|(Setting->RxTimeout >> 8);
		if (Setting->CrcOn)
		{
			Reg[REG_LR_MODEMCONFIG2 - REG_LR_MODEMCONFIG1] |= RFLR_SX1276_MODEMCONFIG2_RXPAYLOADCRC_ON;
		}

		if (LowData)
		{
			Temp = RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON;
		}
		else
		{
			Temp = 0;
		}
    	if (Setting->AGCAuto)
    	{
    		Temp |= RFLR_MODEMCONFIG3_AGCAUTO_ON;
    	}

    	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_MODEMCONFIG3, Temp);
    	if (Error)
    		return Error;
    	if (Setting->HopPeriod)
    	{
    		Error = SX127X_ModifyAndVerifyReg(SpiID, REG_LR_SX1276_PLLHOP, RFLR_PLLHOP_FASTHOP_MASK, RFLR_PLLHOP_FASTHOP_ON);
    		if (Error)
    			return Error;
    	}

        if( ( Setting->Bandwidth == SX127X_LORA_BW_500K ) && ( Setting->CurFreq > RF_MID_BAND_THRESH ) )
        {
            // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
        	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_TEST36, 0x02);
    		if (Error)
    			return Error;
        	Error = SX127X_WriteReg(SpiID, REG_LR_TEST3A, 0x64);
    		if (Error)
    			return Error;
        }
        else if( Setting->Bandwidth == SX127X_LORA_BW_500K )
        {
            // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
        	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_TEST36, 0x02);
    		if (Error)
    			return Error;
        	Error = SX127X_WriteReg(SpiID, REG_LR_TEST3A, 0x7F);
    		if (Error)
    			return Error;
        }
        else
        {
            // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
        	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_TEST36, 0x03);
    		if (Error)
    			return Error;
        	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_TEST2F, 0x40);
    		if (Error)
    			return Error;
        	Error = SX127X_WriteAndVerifyReg(SpiID, REG_LR_TEST30, 0x00);
    		if (Error)
    			return Error;

        }

        if ( Setting->Bandwidth == SX127X_LORA_BW_500K )
        {
        	Temp = SX127X_ReadReg(SpiID, REG_LR_DETECTOPTIMIZE, &Error);
        	Temp = Temp | 0x80;
        	SX127X_WriteReg(SpiID, REG_LR_DETECTOPTIMIZE, Temp);
        }
        else
        {
        	Temp = SX127X_ReadReg(SpiID, REG_LR_DETECTOPTIMIZE, &Error);
        	Temp = Temp & 0x7f;
        	SX127X_WriteReg(SpiID, REG_LR_DETECTOPTIMIZE, Temp);
        }
    	break;
    default:
    	return -ERROR_PARAM_ILLEGAL;
    }
    DBG_HexPrintf(Reg, 8);
    Buf[0] = REG_LR_MODEMCONFIG1|0x80;
    memcpy(Buf + 1, Reg, 8);
    Error = SX127X_SPISync(SpiID, Buf, 9);
	if (Error)
		return Error;
	Buf[0] = REG_LR_MODEMCONFIG1;
    Error = SX127X_SPISync(SpiID, Buf, 9);
	if (Error)
		return Error;
	if (memcmp(Buf + 1, Reg, 8))
	{
		DBG_HexPrintf(Buf + 1, 8);
		DBG_HexPrintf(Reg, 8);
		return -ERROR_DEV_OP_FAIL;
	}

	Setting->NewConfig = 0;
	return ERROR_NONE;
}

int32_t SX127X_SetTx(uint8_t SpiID)
{

	if (SX127X_DisableIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_ClearIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_EnableIrq(SpiID, RFLR_IRQFLAGS_TXDONE|RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_WriteAndVerifyReg(SpiID, REG_LR_FIFOADDRPTR, 0))
		return -ERROR_DEV_OP_FAIL;
	return SX127X_ModifyAndVerifyReg(SpiID, REG_DIOMAPPING1, RFLR_DIOMAPPING1_DIO0_MASK, RFLR_DIOMAPPING1_DIO0_01);
}

int32_t SX127X_SetRx(uint8_t SpiID)
{

	if (SX127X_DisableIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_ClearIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_EnableIrq(SpiID, RFLR_IRQFLAGS_RXDONE|RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_WriteAndVerifyReg(SpiID, REG_LR_FIFOADDRPTR, 0))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_WriteAndVerifyReg( SpiID, REG_LR_FIFORXBASEADDR, 0 ))
		return -ERROR_DEV_OP_FAIL;
	return SX127X_ModifyAndVerifyReg(SpiID, REG_DIOMAPPING1, RFLR_DIOMAPPING1_DIO0_MASK, RFLR_DIOMAPPING1_DIO0_00);
}

int32_t SX127X_SetCAD(uint8_t SpiID)
{

	if (SX127X_DisableIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_ClearIrq(SpiID, 0xff))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_EnableIrq(SpiID, RFLR_IRQFLAGS_CADDONE|RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL))
		return -ERROR_DEV_OP_FAIL;
	if (SX127X_WriteAndVerifyReg(SpiID, REG_LR_FIFOADDRPTR, 0))
		return -ERROR_DEV_OP_FAIL;
	return SX127X_ModifyAndVerifyReg(SpiID, REG_DIOMAPPING1, RFLR_DIOMAPPING1_DIO0_MASK, RFLR_DIOMAPPING1_DIO0_00);
}

int32_t SX127X_Tx(uint8_t SpiID)
{
	return SX127X_SetOpModeWithoutCheck(SpiID, RFLR_OPMODE_TRANSMITTER );
}

int32_t SX127X_RxGetDataAsync(uint8_t SpiID, uint8_t *Buf, uint8_t *RxLen)
{
	int32_t Error;
	uint8_t Start,NB;
	Start = SX127X_ReadReg(SpiID, REG_LR_FIFORXCURRENTADDR, &Error);
	if (Error)
		return Error;
	NB = SX127X_ReadReg(SpiID, REG_LR_RXNBBYTES, &Error);
	if (Error)
		return Error;
	if (SX127X_WriteAndVerifyReg(SpiID, REG_LR_FIFOADDRPTR, Start))
		return -ERROR_DEV_OP_FAIL;
	SX_API_DBG("%02x %d", Start, NB);
	*RxLen = NB;
	return SX127X_ReadfifoASync(SpiID, Buf, NB);
}

int32_t SX127X_TestMode(uint8_t SpiID, uint32_t Freq, int8_t Power)
{
	return -ERROR_DEV_OP_FAIL;
}

int32_t SX127X_CheckVersion(uint8_t SpiID, uint8_t Version)
{
	int32_t Error;
	if ( (Version == SX127X_ReadReg(SpiID, REG_VERSION, &Error) ) && !Error)
	{
		return ERROR_NONE;
	}
	else
	{
    	if (Error)
    		return Error;
    	return -ERROR_DEV_OP_FAIL;
	}
}
